/*
 ------------------------------------------------------------------------------
	willy-player - a simple music player based on SDL.

	Copyright (C) 2011 Pierre Veber
	
	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 3 of the License, or
	(at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software Foundation,
	Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
------------------------------------------------------------------------------
*/

#include "precomp.h"

HAudioLib		_g_hLib		= NULL;
char*			_g_pszLib	= NULL;
char*			_g_pszConf	= NULL;
char*			_g_pszPlay	= NULL;

/*View_t* pCurrentView = NULL;

MediaFile_t* _gp_Current = NULL;

char* pszFileToPlay = NULL;*/

/*
 ------------------------------------------------------------------------------
	UI Specs
 ------------------------------------------------------------------------------
*/

/* size */
int _gi_AppWidth	= 320;
int _gi_AppHeight	= 480;

/*View_t* _view_show(View_t* pView)
{
	if (pCurrentView != NULL)
	{
		pCurrentView->fpHandleUIMessage(pCurrentView, UI_SHOW, NULL, 0);
	}
	pCurrentView = pView;
	pCurrentView->fpHandleUIMessage(pCurrentView, UI_SHOW, NULL, 1);
	return pCurrentView;
}*/

/*
 ------------------------------------------------------------------------------
	Lib Status Changed Handler.

		Sends a SDL event to UI Thread.
 ------------------------------------------------------------------------------
*/

int onLibStatusChange(AudioLib_t* pLib, int iStatus)
{
	SDL_Event event;

	TRACE1("Lib status changed to %d!", iStatus);

	/* signal that library is accessible in dir mode */
	event.type = SDL_USEREVENT;
	event.user.code = EVENT_LIB_STATUS_CHANGED;
	event.user.data1 = (void*)iStatus;
	event.user.data2 = (void*)pLib;

	SDL_PushEvent(&event);

	return 0;
}

/*
 ------------------------------------------------------------------------------
	_wp_do_command

		Executes command line:
		- stores the file to play when lib is ready.
		- loads and fills corresponding audio lib.
 ------------------------------------------------------------------------------
*/

int _wp_do_command(const char* arg)
{
	char* pszUserDir;
	char* pszNewLib = _g_pszLib;

	if (_g_hLib == NULL)
	{
		/* first launch: */
		/* read configuration file */
		pszUserDir = _wp_user_store();
		if (pszUserDir != NULL)
		{
			_g_pszConf = _path_append(pszUserDir, "willy-player.conf");
			if (_g_pszConf != NULL)
			{
				pszNewLib = _wp_conf_read(_g_pszConf, "Libraries", "Library0");
			}
			free(pszUserDir);
		}
	}
	_g_pszPlay = NULL;

	/* if parameter not empty */
	if (arg[0] != '\0')
	{
		/* ...and is a folder */
		if (_path_is_dir(arg))
		{
			pszNewLib = _strdup(arg);
			_g_pszPlay = NULL;
		}
		/* or is a file: */
		else
		{
			char* pszRoot = _path_find_dir(arg);
			if (pszRoot != NULL)
			{
				/* do we need to update the lib? */
				if ( (_g_pszLib == NULL) || (strstr(pszRoot, _g_pszLib) == NULL) )
				{
					pszNewLib = _strdup(pszRoot);
				}
				_g_pszPlay = _strdup(arg);
				free(pszRoot);
			}
		}
	}

	/* load the new lib? */
	if (pszNewLib != _g_pszLib)
	{
		if (_g_hLib != NULL)
		{
			libFree(_g_hLib);
			free(_g_pszLib);
		}
		_g_pszLib = pszNewLib;
		_g_hLib = libCreate(_g_pszLib);
		if (_g_hLib != NULL)
		{
			libFill(_g_hLib, onLibStatusChange);
		}
	}
	else
	{
		if (_g_pszPlay)
		{
			/* just play the file */
			SDL_Event event;

			/* signal that library is accessible in dir mode */
			event.type = SDL_USEREVENT;
			event.user.code = EVENT_CMD_PLAYFILE;
			event.user.data1 = (void*)_g_pszPlay;
			event.user.data2 = (void*)0;

			SDL_PushEvent(&event);
		}
	}

	return 0;
}

/*
 ------------------------------------------------------------------------------
	_wp_ui_thread

		UI Thread procedure:
		- do all inits
		- main UI SDL event polling
		- closes everything on exit
 ------------------------------------------------------------------------------
*/

int _wp_ui_thread(HThread hThread, void* pData)
{
	SDL_Event event;
	HAudioDevice hAudio = NULL;
	HPlayer	hPlayer	= NULL;
	SDL_Surface* pScreen = NULL;


	if (SDL_Init(SDL_INIT_VIDEO) < 0)
	{
		TRACE1("Could not initialize SDL: %s", SDL_GetError());
		return 1;
	}
	
	if (TTF_Init() == -1)
	{
		TRACE1("Could not initialize SDL_TTF: %s", TTF_GetError());
		return 1;
	}	

	if (IMG_Init(IMG_INIT_JPG|IMG_INIT_PNG) == -1)
	{
		TRACE1("Could not initialize SDL_IMG: %s", IMG_GetError());
		return 1;
	}	

	pScreen = SDL_SetVideoMode(_gi_AppWidth, _gi_AppHeight, 0, SDL_HWPALETTE);
	if (pScreen == NULL)
	{
		TRACE1("Couldn't set screen mode: %s", SDL_GetError());
		return 1;
	}

	SDL_WM_SetCaption("willy-player", NULL);
	//SDL_WM_SetIcon(IMG_Load("resources/willy-player.png"), NULL);

	/* execute willy-player command */
	_wp_do_command((const char*)pData);

	//pLib = _media_lib_new("C:\\Users\\pveber\\Documents\\Storage\\Music\\30 Seconds To Mars"); */
	/*if (pLib != NULL)
	{
		pFlatView = CreateFlatView();
		_view_show(pFlatView);
		_media_lib_fill(pLib);
	}*/
	
	while(SDL_WaitEvent(&event))
	{
		//if ( (pCurrentView == NULL) || (pCurrentView->fpHandleEvent(pCurrentView, &event)) )
		//{
			if (event.type == SDL_QUIT)
			{
				break;
			}
			else if (event.type == SDL_USEREVENT)
			{
				if (event.user.code == EVENT_CMD_PLAYFILE)
				{
					/* play the file */
					AudioFile_t* pFile = playlistLookupFile(playlistFromLib(_g_hLib), (char*)event.user.data1);
					if (pFile != NULL)
					{
						if (hPlayer == NULL)
						{
							hPlayer = playerCreate(hAudio);
						}
						if (hPlayer == NULL)
						{
							/* display some error ? */
							TRACE("Couldn't create player!");
							break;
						}
						playerQueue(hPlayer, pFile);
						playerResume(hPlayer);
					}

				}
				else if (event.user.code == EVENT_CMD_ENTRYPOINT)
				{
					TRACE1("Entry point event received, command: %s", event.user.data1);
					_wp_do_command((const char*)event.user.data1);
					_wp_release_instance_data();
				}
				else if (event.user.code == EVENT_LIB_STATUS_CHANGED)
				{
					if (hAudio == NULL)
					{
						/* init audio */
						hAudio = waveOpen();
						if (hAudio == NULL)
						{
							/* display some error box */
							TRACE("Couldn't open audio device!");
							break;
						}
					}

					if ((int)event.user.data1 == LIB_STATUS_FILE_ACCESS)
					{
						if (_g_pszPlay != NULL)
						{
							/* play the file */
							AudioFile_t* pFile = playlistLookupFile(playlistFromLib(_g_hLib), _g_pszPlay);
							if (pFile != NULL)
							{
								hPlayer = playerCreate(hAudio);
								if (hPlayer == NULL)
								{
									/* display some error ? */
									TRACE("Couldn't create player!");
									break;
								}
								playerQueue(hPlayer, pFile);
								playerResume(hPlayer);
							}
						}
					}
					if ((int)event.user.data1 == LIB_STATUS_ID3_ACCESS)
					{
						/* update UI */
					}
				}
			}
			else if (event.type == SDL_KEYDOWN)
			{
				switch (event.key.keysym.sym)
				{
					case SDLK_RIGHT:
						/*if (seek < 100)
							seek += 10;
						playerSeek(_g_hPlayer, seek);*/
						break;

					case SDLK_LEFT:
						/*if (seek > 0)
							seek -= 10;
						playerSeek(_g_hPlayer, seek);*/
						break;

					case SDLK_ESCAPE:
						/* unstack */
						playerStop(hPlayer);
						break;

					case SDLK_SPACE:
						/* start playback */
						playerPause(hPlayer);
						break;

					default:
						break;
				}
			}
		//}
	}

	if (hAudio != NULL)
	{
		waveClose(hAudio);
	}
	if (_g_hLib != NULL)
	{
		libFree(_g_hLib);
	}
	if (hPlayer != NULL)
	{
		playerDelete(hPlayer);
	}
	if (_g_pszPlay != NULL)
	{
		free(_g_pszPlay);
	}
	if (_g_pszLib != NULL)
	{
		free(_g_pszLib);
	}

	TTF_Quit();
	IMG_Quit();
	SDL_Quit();

	return _wp_terminate_instance();
}

/*
 ------------------------------------------------------------------------------
	_wp_main: entry point, called from platform-specific main functions.

		Initialize system-wide instance data calling _wp_init_instance. This
		instance data is used to control there is no other instance of willy-
		player is running.

		If another instance is running, send command to this instance using
		_wp_signal_instance and quit.

		If no other instance is running, create the UI thread (_wp_ui_thread) 
		and listen for instance signals using _wp_listen_instance.
------------------------------------------------------------------------------
*/

int _wp_main(char* arg)
{
	int unique;

	/* init instance data, return 1 if no other instance is running */
	unique = _wp_init_instance();

	if (unique == -1)
	{
		TRACE("Could not check unicity.");
		return 1;
	}
	else if (unique == 0)
	{
		/* Other instance running, pass argument, signal and quit */
		return _wp_signal_instance(arg);
	}
	else
	{
		/* No other instance running, start UI */
		CreateThread(_wp_ui_thread, arg);
		
		/* Listen to instance signals */
		while (_wp_listen_instance() != 1)
		{
			/* event signalled */
			SDL_Event event;
			
			event.type = SDL_USEREVENT;
			event.user.code = EVENT_CMD_ENTRYPOINT;
			event.user.data1 = (void*)_wp_lock_instance_data();
			event.user.data2 = (void*)NULL;
			
			/* send event to ui */
			SDL_PushEvent(&event);
		}

		/* nicely free instance data */
		_wp_free_instance_data();
	}

	return 0;
}


